﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Web;
using TruyenTranhCrawler.Data;
using TruyenTranhCrawler.Helper;
using TruyenTranhCrawler.Utils;
using log4net;

namespace TruyenTranhCrawler
{
    public class ComicVn
    {
        private static readonly ILog Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        #region ctor
        private static readonly HtmlParser _parser = new HtmlParser();
        private static class Singleton
        {
            public static readonly ComicVn Instance = new ComicVn();
        }
        public static ComicVn Instance
        {
            get
            {
                return Singleton.Instance;
            }
        }
        #endregion

        #region Config

        private const string DomainLink = "http://comicvn.net";
        /// <summary>
        /// /truyentranh/manga/list?page={0}_orderBy=moi_limit=30
        /// </summary>
        const string UrlDataFormat = DomainLink + "/truyentranh/manga/list?page={0}&orderBy=moi&limit=30";

        const string OpenTag = " <div class=\"div_img_cn";
        const string CloseTag = "</div>";

        const string OpenBookInfo = "<div class=\"box_con";
        const string CloseBookInfo = "</div>";

        const string OpenTagDescipt = "<div class=\"name_dich\"";
        const string CloseTagDescript = "</div>";

        const string OpenChapItem = "<div class=\"table_line";
        const string CloseChapItem = "</div>";

        #endregion

        /// <summary>
        /// Xem page 1, neu co truyen moi thi bat dau lay het cac page con lai. ko thi bo qua
        /// </summary>
        /// <returns></returns>
        public List<Book> GetBooks()
        {
            var results = new List<Book>();
            Logger.Info("*** kiem tra xem co book nao moi hoac updated hay khong");
            int total = 0;

            int page = 0;
            while (true)
            {
                var isUpdatedInPage = false;
                page++;
                var sources = Process.GetHtmlSources(string.Format(UrlDataFormat, page));
                if (sources.Length > 0)
                {
                    sources = _parser.Replace(sources, HtmlParser.Patterns.BREAK, " ");
                    var matchs = _parser.GetContentInNode(sources, OpenTag, CloseTag);
                    foreach (string m in matchs)
                    {
                        try
                        {
                            var book = new Book
                            {
                                CrawlHost = "comicvn",
                                Source = "comicvn"
                            };
                            var links = _parser.GetBetweenTag(m, "a");
                            foreach (Match link in links)
                            {
                                if (link.Value.IndexOf("a_name_cn") >= 0)
                                {
                                    var crawlUrl = _parser.GetProperty(link.Value, "href")[0].Groups[4].Value.Trim();
                                    book.CrawlUrl =
                                        HttpUtility.HtmlDecode(Process.FillAbsoluteLink(DomainLink, crawlUrl));

                                    book.CrawlName = HttpUtility.HtmlDecode(_parser.RemoveAllTag(link.Value).Trim());
                                    book.FullName = book.CrawlName;
                                    break;
                                }
                            }
                            if (string.IsNullOrEmpty(book.CrawlUrl)) continue;

                            //get last chap
                            var blocks = _parser.GetContentInNode(m, "<div class=\"chap_update", "</div>");
                            if (blocks.Count > 0)
                            {
                                var lastUrl = _parser.GetProperty(blocks[0], "href")[0].Groups[4].Value.Trim();
                                lastUrl = HttpUtility.HtmlDecode(Process.FillAbsoluteLink(DomainLink, lastUrl));

                                if (Book.CanbeCrawl(ref book))
                                {
                                    if (book.ID == 0 || Content.IsNotExisted(book.ID, lastUrl))
                                    {
                                        isUpdatedInPage = true;
                                        var checker = results.Find(b => b.CrawlUrl == book.CrawlUrl);   //check duplicate item
                                        if (checker == null)
                                        {
                                            results.Add(book);
                                            total++;
                                        }
                                    }
                                }
                            }
                            else
                            {
                                Logger.Info("Khong lay duoc last chap Url de sosanh, hay vao kiem tra CODE: <div class=\"chap_update\">...</div> " + book.CrawlUrl);
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex);
                        }
                    }

                    if (!isUpdatedInPage)
                        break;
                }
                else
                {
                    break;
                }
            }
            Logger.Info(string.Format("xong new updated: {0}", total));

            return results;
        }
        /// <summary>
        /// Lay tat ca thong tin cua Book
        /// </summary>
        public int GetNewChaps(Book b)
        {
            int newcount = 0;
            var sources = Process.GetHtmlSources(b.CrawlUrl);
            if (sources.Length > 0)
            {
                sources = _parser.Replace(sources, HtmlParser.Patterns.BREAK, " ");
                var ss = _parser.GetContentInNode(sources, OpenBookInfo, CloseBookInfo);
                if (ss.Count > 0)
                {
                    var s = ss[0];
                    try
                    {
                        var isChanged = false;
                        if (string.IsNullOrEmpty(b.Image))
                        {
                            var img = Process.GetFirstImg(s);
                            if (!_parser.Matched(img, Config.GoogleHostPattern))
                            {
                                //upload to picasa
                                b.SortName = BaseObject.GetSortName(b.FullName);
                                var imginfos = ImageHelper.GetImage(img, b.SortName, Config.BookFolder);
                                if (!string.IsNullOrEmpty(imginfos[0]))
                                {
                                    img = imginfos[0];
                                }
                            }
                            b.Image = img;
                            isChanged = true;
                        }
                        var blocks = _parser.GetContentInNode(s, OpenTagDescipt, CloseTagDescript);
                        foreach (var block in blocks)
                        {
                            if (_parser.Matched(block, "sơ lược") && string.IsNullOrEmpty(b.Description))
                            {
                                var desc = _parser.Replace(blocks[0], "(sơ lược|:)", "").Trim();
                                desc = _parser.RemoveTagOnly(desc, new string[] { "span", "div", "a", "script" });
                                b.Description = HttpUtility.HtmlDecode(desc);
                                isChanged = true;
                            }
                            else if (_parser.Matched(block, "Thể loại") && string.IsNullOrEmpty(b.Types))
                            {
                                var hrefs = _parser.GetProperty(block, "href");
                                var types = (from Match hr in hrefs select hr.Groups[4].Value.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries)).Aggregate("", (current, strings) => current + (HistoryType.GetTypeNameMatched(strings[strings.Length - 1], TypeFromSourceWeb.ComicVn) + ","));
                                if (types.Length > 0)
                                {
                                    b.Types = types.Remove(types.Length - 1);
                                    isChanged = true;
                                }
                            }
                            else if (_parser.Matched(block, "Tác giả") && string.IsNullOrEmpty(b.CrawlAuthor))
                            {
                                var cleartext = HttpUtility.HtmlDecode(_parser.RemoveAllTag(block));
                                b.CrawlAuthor = _parser.Replace(cleartext, "(tác giả|:)", "").Trim();
                                isChanged = true;
                            }
                            else if (_parser.Matched(block, "Số chap") && _parser.Matched(block, "Hoàn thành"))
                            {
                                b.Finish = true;
                                isChanged = true;
                            }
                        }

                        if (b.ID == 0)
                        {
                            b.Save();
                        }
                        else if (isChanged)
                        {
                            b.Update();
                        }
                        var ccl = new CommonCrawler();
                        //get list chapter
                        var allExisted = Content.FindByBook(b.ID).Select(x => x.CrawlUrl).ToList();

                        var allChapFromSource = _parser.GetContentInNode(s, OpenChapItem, CloseChapItem);
                        if (allChapFromSource.Count > 0)
                        {
                            int totalFromSource = allChapFromSource.Count;
                            if (totalFromSource > allExisted.Count)
                            {
                                var lastChapId = 0;
                                var idx = 1;
                                //(index =0 la chuong moi nhat)
                                while (idx <= totalFromSource)
                                {
                                    var tagAs = _parser.GetBetweenTag(allChapFromSource[totalFromSource - idx], "a");
                                    if (tagAs.Count > 0)
                                    {
                                        var urls = _parser.GetProperty(tagAs[0].Value, "href");
                                        if (urls.Count > 0)
                                        {
                                            var chap = new Content { Book_ID = b.ID, Chapter = allExisted.Count + 1, SafeNameBook = b.SafeName };
                                            var crawlUrl = urls[0].Groups[4].Value.Trim();
                                            chap.CrawlUrl = Process.FillAbsoluteLink(DomainLink, crawlUrl);

                                            if (!allExisted.Contains(chap.CrawlUrl))
                                            {
                                                allExisted.Add(chap.CrawlUrl); //add into existed

                                                chap.Title = HttpUtility.HtmlDecode(_parser.RemoveAllTag(tagAs[0].Value).Trim());
                                                chap.Body = ccl.GetChapBody(chap.CrawlUrl);
                                                chap.Broken = chap.Body.Length == 0;
                                                chap.Save();
                                                lastChapId = chap.Content_ID;

                                                newcount++;
                                            }
                                        }
                                    }
                                    
                                    idx++;
                                }
                                if (lastChapId > 0)
                                    Book.UpdateLastChap(b.ID, lastChapId, allExisted.Count);
                            }
                        }
                        if (newcount > 0)
                            Logger.Info(string.Format("New chap for book ID:{0}, sortname:{1}, finish: {2}, total chap:{3}", b.ID, b.SortName, b.Finish, newcount));
                    }
                    catch (Exception ex)
                    {
                        Logger.Error(ex);
                    }
                }
            }
            return newcount;
        }

    }
}

